package com.ctcf.ocr.engine.impl.utils;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.imageio.ImageIO;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;

public class HttpRequestUtils {

	private static Logger logger = LoggerFactory.getLogger(HttpRequestUtils.class);

	/** 默认UTF-8编码 */
	private static String defaultCharset = "UTF-8";

	/** application/json */
	private static String contentType = "application/json";

	private static CloseableHttpClient myHttpClient = null;

	private static CloseableHttpClient httpSSLClient = null;

	static {
		RequestConfig config = RequestConfig.custom().setConnectTimeout(60000).setSocketTimeout(15000).build();
		myHttpClient = HttpClientBuilder.create().setDefaultRequestConfig(config).build();

		try {
			httpSSLClient = new SSLClient();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static JSONObject httpPost(String url, JSONObject jsonParam) {
		// post请求返回结果

		JSONObject jsonResult = null;
		HttpPost method = new HttpPost(url);
		try {
			if (null != jsonParam) {
				// 解决中文乱码问题
				StringEntity entity = new StringEntity(jsonParam.toString(), defaultCharset);
				entity.setContentEncoding(defaultCharset);
				entity.setContentType(contentType);
				method.setEntity(entity);
			}
			CloseableHttpClient httpClient = getHttpClient(url);
			HttpResponse result = httpClient.execute(method);
			url = URLDecoder.decode(url, defaultCharset);
			/** 请求发送成功，并得到响应 **/
			if (result.getStatusLine().getStatusCode() == 200) {
				String strResult = "";
				try {
					/** 读取服务器返回过来的json字符串数据 **/
					strResult = EntityUtils.toString(result.getEntity());

					/** 把json字符串转换成json对象 **/
					jsonResult = JSONObject.parseObject(strResult);

				} catch (Exception e) {
					logger.error("post请求提交失败:" + url, e);
				}
			}
		} catch (IOException e) {
			logger.error("post请求提交失败:" + url, e);
		}
		return jsonResult;
	}

	public static JSONObject httpGet(String url) {
		// get请求返回结果
		JSONObject jsonResult = null;
		try {
			CloseableHttpClient httpClient = getHttpClient(url);
			// 发送get请求
			HttpGet request = new HttpGet(url);
			HttpResponse response = httpClient.execute(request);

			/** 请求发送成功，并得到响应 **/
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				/** 读取服务器返回过来的json字符串数据 **/
				String strResult = EntityUtils.toString(response.getEntity());
				/** 把json字符串转换成json对象 **/
				jsonResult = JSONObject.parseObject(strResult);

				url = URLDecoder.decode(url, defaultCharset);
			} else {
				logger.error("get请求提交失败:" + url);
			}
		} catch (IOException e) {
			logger.error("get请求提交失败:" + url, e);
		}
		return jsonResult;
	}

	public static String doGet(String url, Map<String, String> params) {
		return doGet(url, params, defaultCharset);
	}

	public static String doPost(String url, JSONObject params) {
		return doPost(url, params, defaultCharset);
	}

	public static String doGet(String url, Map<String, String> params, String charset) {
		if (StringUtils.isBlank(url)) {
			return null;
		}

		try {
			CloseableHttpClient httpClient = getHttpClient(url);

			if (params != null && !params.isEmpty()) {
				List<BasicNameValuePair> pairs = new ArrayList<BasicNameValuePair>(params.size());
				for (Map.Entry<String, String> entry : params.entrySet()) {
					String value = entry.getValue();
					if (value != null) {
						pairs.add(new BasicNameValuePair(entry.getKey(), value));
					}
				}
				url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, charset));
			}
			HttpGet httpGet = new HttpGet(url);

			CloseableHttpResponse response = httpClient.execute(httpGet);
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode != HttpStatus.SC_OK) {
				httpGet.abort();
				throw new RuntimeException("HttpClient,error status code :" + statusCode);
			}
			HttpEntity entity = response.getEntity();
			String result = null;
			if (entity != null) {
				result = EntityUtils.toString(entity, charset);
			}
			EntityUtils.consume(entity);
			response.close();
			httpClient.close();
			return result;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static String doPost(String url, JSONObject params, String charset) {
		if (StringUtils.isBlank(url)) {
			return null;
		}

		try {
			HttpPost httpPost = new HttpPost(url);
			if (params != null && params.size() > 0) {
				// 解决中文乱码问题
				StringEntity entity = new StringEntity(params.toJSONString(), defaultCharset);
				entity.setContentEncoding(defaultCharset);
				entity.setContentType(contentType);
				httpPost.setEntity(entity);
			}
			CloseableHttpClient httpClient = getHttpClient(url);
			CloseableHttpResponse response = httpClient.execute(httpPost);
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode != 200) {
				httpPost.abort();
				throw new RuntimeException("HttpClient,error status code :" + statusCode);
			}
			HttpEntity entity = response.getEntity();
			String result = null;
			if (entity != null) {
				result = EntityUtils.toString(entity, charset);
			}
			EntityUtils.consume(entity);
			response.close();
			return result;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static CloseableHttpClient getHttpClient(String url) {
		CloseableHttpClient closeableHttpClient = null;
		if (url.toLowerCase().startsWith("https")) {
			closeableHttpClient = httpSSLClient;
		} else {
			closeableHttpClient = myHttpClient;
		}
		return closeableHttpClient;
	}

	/**
	 * 下载验证码图片
	 * 
	 * @param url
	 * @param params
	 * @return
	 */
	public static void doGetImage(String url, Map<String, String> params, Map<String, String> headers, int i) {
		if (StringUtils.isBlank(url)) {
			return;
		}
		CloseableHttpClient httpClient = getHttpClient(url);
		try {

			if (params != null && !params.isEmpty()) {
				List<BasicNameValuePair> pairs = new ArrayList<BasicNameValuePair>(params.size());
				for (Map.Entry<String, String> entry : params.entrySet()) {
					String value = entry.getValue();
					if (value != null) {
						pairs.add(new BasicNameValuePair(entry.getKey(), value));
					}
				}
				url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, defaultCharset));
			}

			HttpGet httpGet = new HttpGet(url);

			if (headers != null && headers.size() > 0) {
				Set<Entry<String, String>> sEntries = headers.entrySet();
				for (Entry<String, String> entry : sEntries) {
					httpGet.addHeader(entry.getKey(), entry.getValue());
				}
			}

			CloseableHttpResponse response = httpClient.execute(httpGet);
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode != HttpStatus.SC_OK) {
				httpGet.abort();
				throw new RuntimeException("HttpClient,error status code :" + statusCode);
			}
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				InputStream in = entity.getContent();
				saveImageFile(in, i);
			}
			EntityUtils.consume(entity);
			response.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {

		}
	}

	/**
	 * 下载验证码图片
	 * 
	 * @param url
	 * @param params
	 * @return
	 */
	public static BufferedImage doGetImage(String url, Map<String, String> params, Map<String, String> headers) {
		if (StringUtils.isBlank(url)) {
			return null;
		}
		CloseableHttpClient httpClient = getHttpClient(url);
		InputStream in = null;
		BufferedImage bufferedImage = null;
		try {

			if (params != null && !params.isEmpty()) {
				List<BasicNameValuePair> pairs = new ArrayList<BasicNameValuePair>(params.size());
				for (Map.Entry<String, String> entry : params.entrySet()) {
					String value = entry.getValue();
					if (value != null) {
						pairs.add(new BasicNameValuePair(entry.getKey(), value));
					}
				}
				url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, defaultCharset));
			}

			HttpGet httpGet = new HttpGet(url);

			if (headers != null && headers.size() > 0) {
				Set<Entry<String, String>> sEntries = headers.entrySet();
				for (Entry<String, String> entry : sEntries) {
					httpGet.addHeader(entry.getKey(), entry.getValue());
				}
			}

			CloseableHttpResponse response = httpClient.execute(httpGet);
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode != HttpStatus.SC_OK) {
				httpGet.abort();
				throw new RuntimeException("HttpClient,error status code :" + statusCode);
			}
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				in = entity.getContent();
				bufferedImage = ImageIO.read(in);
			}
			EntityUtils.consume(entity);
			response.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (in != null) {
					in.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return bufferedImage;
	}

	@SuppressWarnings("restriction")
	public static BufferedImage decodeToImage(String imageString) {

		BufferedImage image = null;
		byte[] imageByte;
		try {
			sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
			imageByte = decoder.decodeBuffer(imageString);
			ByteArrayInputStream bis = new ByteArrayInputStream(imageByte);
			image = ImageIO.read(bis);
			bis.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return image;
	}

	@SuppressWarnings("restriction")
	public static String encodeToString(BufferedImage image, String type) {
		String imageString = null;
		ByteArrayOutputStream bos = new ByteArrayOutputStream();

		try {
			ImageIO.write(image, type, bos);
			byte[] imageBytes = bos.toByteArray();
			sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
			imageString = encoder.encode(imageBytes);
			bos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return imageString;
	}

	private static void saveImageFile(InputStream in, int i) {
		try {
			String dirPath = "/Library/apache-tomcat-7.0.69/webapps/ocr.engine.web/WEB-INF/classes/testResources/";
			File dir = new File(dirPath);
			if (dir == null || !dir.exists()) {
				dir.mkdirs();
			}

			// 文件真实路径
			String realPath = dirPath.concat("code" + String.valueOf(i) + ".jpg");
			File file = new File(realPath);

			FileOutputStream fos = new FileOutputStream(file);
			byte[] buf = new byte[1024];
			int len = 0;
			while ((len = in.read(buf)) != -1) {
				fos.write(buf, 0, len);
			}
			fos.flush();
			fos.close();
			System.out.println("下载完成：" + file.getPath());

		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public static void downloadPbcVerifyCode(int count) {

		String url = "https://ipcrs.pbccrc.org.cn/imgrc.do";
		Map<String, String> params = new HashMap<String, String>();
		long timestamp = System.currentTimeMillis();
		params.put("a", String.valueOf(timestamp));
		Map<String, String> headers = new HashMap<String, String>();
		headers.put("Accept", "image/webp,image/*,*/*;q=0.8");
		headers.put("Cache-Control", "no-cache");
		headers.put("Host", "ipcrs.pbccrc.org.cn");
		headers.put("Referer", "https://ipcrs.pbccrc.org.cn/page/login/loginreg.jsp");
		headers.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36");

		for (int i = 1; i <= count; i++) {
			System.out.println("正在下载第" + i + "张验证码...");
			HttpRequestUtils.doGetImage(url, params, headers, i);
		}

		System.out.println("完成测试");
	}

	// 下载人行验证码
	public static BufferedImage fetchPbcVerifyCode() {

		String url = "https://ipcrs.pbccrc.org.cn/imgrc.do";
		Map<String, String> params = new HashMap<String, String>();
		long timestamp = System.currentTimeMillis();
		params.put("a", String.valueOf(timestamp));
		Map<String, String> headers = new HashMap<String, String>();
		headers.put("Accept", "image/webp,image/*,*/*;q=0.8");
		headers.put("Cache-Control", "no-cache");
		headers.put("Host", "ipcrs.pbccrc.org.cn");
		headers.put("Referer", "https://ipcrs.pbccrc.org.cn/page/login/loginreg.jsp");
		headers.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36");

		BufferedImage image = HttpRequestUtils.doGetImage(url, params, headers);
		
		return image;
	}

	public static void main(String[] args) {
		downloadPbcVerifyCode(100);
	}
}
